#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>

using namespace std;

// 方向枚举
enum Direction { UP, DOWN, LEFT, RIGHT };

// 点结构
struct Point {
    int x, y;
    Point(int x = 0, int y = 0) : x(x), y(y) {}
};

class SnakeGame {
private:
    int width, height;
    vector<Point> snake;
    Point food;
    Direction dir;
    bool gameOver;
    int score;

public:
    SnakeGame(int w = 20, int h = 10) : width(w), height(h), gameOver(false), score(0) {
        srand(time(0));
        snake.push_back(Point(width / 2, height / 2));
        generateFood();
        dir = RIGHT;
    }

    void generateFood() {
        do {
            food.x = rand() % (width - 2) + 1;
            food.y = rand() % (height - 2) + 1;
        } while (isSnake(food));
    }

    bool isSnake(Point p) {
        for (auto& s : snake) {
            if (s.x == p.x && s.y == p.y) return true;
        }
        return false;
    }

    void draw() {
        system("clear"); // Linux系统清屏

        // 绘制顶部边框
        for (int i = 0; i < width; i++) cout << "#";
        cout << endl;

        // 绘制游戏区域
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (x == 0 || x == width - 1) cout << "#";
                else if (x == food.x && y == food.y) cout << "F";
                else if (isSnake(Point(x, y))) {
                    if (snake[0].x == x && snake[0].y == y) cout << "O";
                    else cout << "o";
                }
                else cout << " ";
            }
            cout << endl;
        }

        // 绘制底部边框
        for (int i = 0; i < width; i++) cout << "#";
        cout << endl;

        // 显示分数
        cout << "Score: " << score << endl;
        cout << "Use WASD to control, Q to quit" << endl;
    }

    void input() {
        if (_kbhit()) {
            switch (getch()) {
                case 'w': if (dir != DOWN) dir = UP; break;
                case 's': if (dir != UP) dir = DOWN; break;
                case 'a': if (dir != RIGHT) dir = LEFT; break;
                case 'd': if (dir != LEFT) dir = RIGHT; break;
                case 'q': gameOver = true; break;
            }
        }
    }

    void logic() {
        Point head = snake[0];

        // 根据方向移动头部
        switch (dir) {
            case UP: head.y--; break;
            case DOWN: head.y++; break;
            case LEFT: head.x--; break;
            case RIGHT: head.x++; break;
        }

        // 检查是否撞墙
        if (head.x <= 0 || head.x >= width - 1 || head.y < 0 || head.y >= height) {
            gameOver = true;
            return;
        }

        // 检查是否撞到自己
        for (size_t i = 1; i < snake.size(); i++) {
            if (head.x == snake[i].x && head.y == snake[i].y) {
                gameOver = true;
                return;
            }
        }

        // 将新头部添加到蛇身
        snake.insert(snake.begin(), head);

        // 检查是否吃到食物
        if (head.x == food.x && head.y == food.y) {
            score += 10;
            generateFood();
        } else {
            // 如果没吃到食物，移除尾部
            snake.pop_back();
        }
    }

    // 非阻塞键盘输入函数
    bool _kbhit() {
        struct termios oldt, newt;
        int ch;
        int oldf;

        tcgetattr(STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &newt);
        oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
        fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

        ch = getchar();

        tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
        fcntl(STDIN_FILENO, F_SETFL, oldf);

        if (ch != EOF) {
            ungetc(ch, stdin);
            return true;
        }

        return false;
    }

    char getch() {
        struct termios oldt, newt;
        int ch;
        tcgetattr(STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &newt);
        ch = getchar();
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
        return ch;
    }

    void run() {
        while (!gameOver) {
            draw();
            input();
            logic();
            usleep(100000); // 100ms延迟
        }
        cout << "Game Over!" << endl;
    }
};

int main() {
    SnakeGame game(40, 20);
    game.run();
    return 0;
}